{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "
\n",
" Si c'est votre première visite dans ce TP, lisez attentivement chacun des points détaillé après ce paragraphe.
\n",
" Si vous avez déjà commencer à travailler sur ce TP et que vous souhaiter vous déplacer rapidement dans une partie précise vous pouvez choisir la partie que vous souhaitez rejoindre ci-dessous.
\n",
" Menu de navigation
\n",
" \n",
"
\n",
" OutilsCrypto.py
\n",
" La technologie jupyter permet d'exécuter du code python par un simple clique sur Executer ci-dessus.
\n",
" Les morceaux de code de cette page sont interprétées case par case. Pour savoir quelle case a été interprétée avant une autre, il suffit de repérer le numéro devant la case.
\n",
" Une fois qu'une case a été interprétée (=exécutée), la page garde en mémoire les variables et fonctions lues
\n",
" La plateforme propose quelques outils de purge de la mémoire : \n",
"
\n",
" Pour ne pas perdre votre travail pensez à le sauvegarder régulièrement. Par défault, la sauvegarde par un clic sur la disquette en haut à gauche de page, ou par le racourci clavier classique ctrl+S
\n",
" est une sauvegarde en local, sur le serveur de jupyter. Vous pouvez et devez très régulièrement sauvegarder votre travail sur votre support personnel de sauvegarde (clef USB, se l'envoyer par mail etc). Ce faisant vous disposerez d'un fichier .ipynb (IPYthon NoteBook) qu'il vous suffira de recharger pour avancer. Après le rechargement assurez vous que les fonctionnalités anciennement developpées et variables utilisées sont bien dans la mémoire de la page (en rééxecutant les cases, ou plus rapidement par Kernel > Restart & Run All.
A NOTER : vous pouvez travailler sur le tp (et tout autre fichier .ipynb) hors connexion en installant une version local du notebook de jupyter. Il faut que votre machine possède un interpreteur de python et que vous soyez connecter à internet.\n", "
pip install jupyterlab
jupyter notebook
OutilsCrypto.py
\n",
"\n",
" Menu de navigation
\n",
" \n",
"
\n",
" OutilsCrypto.py
Une bibliothèque regroupant quelques outils de la cryptologie vous ont été donnée. Chargeons l'intégralité des fonctionnalités qu'elle propose
" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from OutilsCrypto import *" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "codex
Cette fonction applique, comme en cours, le codex pédagogique base de notre étude : le caractère $\\texttt{A}$ est transformé en $0$, le $\\texttt{B}$ en 1 etcaetera jusqu'au $\\texttt{Z}$ qui est transformé en $25$. Exécuter la case suivante pour vous assurer du fonctionnement de cette fonction. Si le caractère n'est pas une lettre entre $\\texttt{A}$ et $\\texttt{Z}$, quel code erreur renverra la fonction ? Que dire de la case ?
" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "x='a'\n", "print(x, \"=\", codex(x))\n", "x='B'\n", "print(x, \"=\", codex(x))\n", "x='c'\n", "print(x, \"=\", codex(x))\n", "x='Z'\n", "print(x, \"=\", codex(x))\n", "x='9'\n", "print(x, \"=\", codex(x))\n", "x='('\n", "print(x, \"=\", codex(x))\n", "x='-'\n", "print(x, \"=\", codex(x))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "xedoc
Cette fonction applique, comme en cours, le codex pédagogique inversé (il s'agit du mot codex à l'envers) : le nombre $25$ renvoie le caractète $\\texttt{Z}$, le chiffre $4$ renvoie le caractère $\\texttt{E}$ etcaetera. Si le nombre n'est pas entre $0$ et $25$, quel code erreur renverra la fonction ? Que dire de la case ?
" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "n=0\n", "print(n, \"=\", xedoc(n))\n", "n=1\n", "print(n, \"=\", xedoc(n))\n", "n=4\n", "print(n, \"=\", xedoc(n))\n", "n=25\n", "print(n, \"=\", xedoc(n))\n", "n=26\n", "print(n, \"=\", xedoc(n))\n", "n=50\n", "print(n, \"=\", xedoc(n))\n", "n=-1\n", "print(n, \"=\", xedoc(n))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "paquet
Cette fonction prend une chaine de caractère txt
et un entier paq
et vas convertir la chaine en un tableau d'entier correspondant aux paquets de lettre de taille paq
. Les paquet seront complété par des $0$ si la longueur de la chaine txt
n'est pas multiple de paq
. Executer la case suivante pour observer le comportement de cette fonction. Cette fonction renvoie en particulier le tableau vide en cas d'erreur
Filtre
Cette fonction prend en paramètre une chaine de caractère et renvoie la même chaine où les caractères spéciaux ou accentués ont été transformé en leur forme génériques (les accents disparaissent). Les espaces et la ponctuation sont enlevés
" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "txt=\"Bonjour\"\n", "print(Filtre(txt))\n", "txt=\"Bonjour ca va ?\"\n", "print(Filtre(txt))\n", "txt=\"Tu me donnes ton 06 stp ?\"\n", "print(Filtre(txt))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "mod2base
Cette fonction prend en paramètre un entier correspondant à la taille des paquets et renvoie le modulo de base de travail.
" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(mod2base())\n", "print(mod2base(1))\n", "print(mod2base(2))\n", "print(mod2base(3))\n", "\n", "print(mod2base(-1))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n",
" Menu de navigation
\n",
" \n",
"
\n",
" OutilsCrypto.py
Ecrire la fonction Ecesar(txt, clef, paq=1)
qui a deux paramètres obligatoire et un paramètre optionnel:\n",
"
txt
: une chaine de caractèreclef
: un entierpaq
: la taille des paquets qui par défaut vaut 1txt
de clef clef
par paquet de paq
. Si paq
vaut 1 alors la fonction devra retourner le décodage des entiers calculer. Sinon la fonction renverra une chaine de caractère correspondant aux entiers chiffrés du message séparé par des $\\texttt{-}$.Ecrire la fonction Dcesar(txt, clef, paq=1)
qui a deux paramètres obligatoire et un paramètre optionnel:\n",
"
txt
: une chaine de caractèreclef
: un entierpaq
: la taille des paquets qui par défaut vaut 1txt
de clef clef
par paquet de paq
. paq
vaut 1 alors txt
est une suite de lettre de l'alphabet. Sinon cette chaine est une suite d'entiers séparés par des $\\texttt{-}$. On pourra récupérer une liste de chaine de caractère des entiers par txt.split('-')
\n",
" Menu de navigation
\n",
" \n",
"
\n",
" OutilsCrypto.py
Dans cette dernière partie, on cherche à déchiffrer le messaque suivant :
\n",
"$$\\texttt{2138-523-1651-1650-712-1434-1834-2338-412-721-212-708}$$ \n",
"
Ecrire une procédure BruteForceCesar(txt, paq=1)
qui teste toutes les clefs possible et affiche, lorsque le message à pu etre décrypter, la liste des déchiffrement possibles.
" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def BruteForceCesar(txt, paq=1) : \n", " try : \n", " txt=str(txt)\n", " paq=int(paq)\n", " except :\n", " print(\"L'attaque ne fonctionne pas\")\n", " return\n", "\n", " clef_valide=0\n", " \n", " print(\"---------------------------------\")\n", " print(\"Début de l'attaque en froce brute\")\n", " print(\"---------------------------------\")\n", " \n", " top=time.time()\n", " \n", " #Mettre votre code ici\n", " \n", " temps=time.time()-top\n", " print(\"Fin de l'attaque | \"+str(clef_valide)+\" clefs valides testées (\"+str(round(temps,3))+\"s)\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
MESSAGE
En observant la liste précédente vous pourrez lire le message décrypter... mais...
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n",
" Menu de navigation
\n",
" \n",
"
\n",
" OutilsCrypto.py
L'inconvenient avec la brute force est qu'il faut lire le message claire dans la liste des messages possible. Une alternative à ce travail de fourmis est d'analyser les messages déchiffrer et de déterminer lequel à le nombre de mot le plus élévé. Pour y arriver on va charger des dictionnaires. Exécuter le code suivant pour charger les différents dictionnaires proposée. ATTENTION : Cette opération peux prendre plusieurs secondes (environ 30). Un message de fin s'affichera lorsque le chargement sera terminé.
" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(\"-----> DéBUT DU CHARGMENT DES DICTIONNAIRES <-----\")\n", "top=time.time()\n", "lang=\"FR\"\n", "print(\"CHARGEMENT DU DICTIONNAIRE \\\"\", lang, \"\\\": \\tEN COURS\",end='')\n", "DICO_FR = MonDico(lang)\n", "print(\"\\rCHARGEMENT DU DICTIONNAIRE \\\"\", lang, \"\\\": \\tTERMINéE (en\", round(time.time()-top, 3), \"secondes)\")\n", "top=time.time()\n", "lang=\"ANG\"\n", "print(\"CHARGEMENT DU DICTIONNAIRE \\\"\", lang, \"\\\": \\tEN COURS\",end='')\n", "DICO_ANG = MonDico(lang)\n", "print(\"\\rCHARGEMENT DU DICTIONNAIRE \\\"\", lang, \"\\\": \\tTERMINéE (en\", round(time.time()-top, 3), \"secondes)\")\n", "top=time.time()\n", "lang=\"ESP\"\n", "print(\"CHARGEMENT DU DICTIONNAIRE \\\"\", lang, \"\\\": \\tEN COURS\",end='')\n", "DICO_ESP = MonDico(lang)\n", "print(\"\\rCHARGEMENT DU DICTIONNAIRE \\\"\", lang, \"\\\": \\tTERMINéE (en\", round(time.time()-top, 3), \"secondes)\")\n", "top=time.time()\n", "lang=\"IT\"\n", "print(\"CHARGEMENT DU DICTIONNAIRE \\\"\", lang, \"\\\": \\tEN COURS\",end='')\n", "DICO_IT = MonDico(lang)\n", "print(\"\\rCHARGEMENT DU DICTIONNAIRE \\\"\", lang, \"\\\": \\tTERMINéE (en\", round(time.time()-top, 3), \"secondes)\")\n", "print(\"-----> FIN DU CHARGMENT DES DICTIONNAIRES <-----\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "pertinence
\n", "Cette fonction prend deux paramètres : \n", "
phrase
: qui est une chaine de caractèredico
: qui est l'un des dictionnaire chargé précédémmentIl en va de même en changeant la langue, qui doit être une donnée a priori et non a posteriori, comme le montre le contre-exemple.
" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "txt=\"BONJOUR\"\n", "print(\"Pertinance FR :\", pertinence(txt, DICO_FR))\n", "print(\"Pertinance ANG :\", pertinence(txt, DICO_ANG))\n", "print(\"Pertinance ESP :\", pertinence(txt, DICO_ESP))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ecrire une procédure BruteForceCesar_dico
qui prend en paramètre : \n",
"
txt
: un chaine de caractère correspondant au message à attaquer.paq
: l'entier correspondant à l'hypothétique nombre de paquet utilisé.DICO
: le dictionnaire correspondant à la langue hypothétique du message claire.MESSAGE
Un chiffrement de César à été utilisé et le message obtenu est le suivant. Attaquez le et donner le nom de la personne qui a prononcé cette phrase à votre enseignant pour obtenir un bonus !\n", "$$\\texttt{62358-63351-235870-63054-124260-52854-43841}$$\n", "
" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "MESSAGE2 = \"62358-63351-235870-63054-124260-52854-43841\"\n", "BruteForceCesar_dico(MESSAGE2, 3, DICO_ANG)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Le MESSAGE3
n'est pas nécessairement en français. Bon chance.